Limit manual flushing so we don't get hit by quartz' fps limiting
authorRichard Hult <richard@imendio.com>
Mon, 9 Feb 2009 14:46:30 +0000 (15:46 +0100)
committerAlexander Larsson <alex@localhost.localdomain>
Thu, 2 Apr 2009 08:16:29 +0000 (10:16 +0200)
gdk/quartz/gdkdrawable-quartz.c
gdk/quartz/gdkprivate-quartz.h
gdk/quartz/gdkwindow-quartz.c

index ce1513e5eac29471e4187f7e77d3c1cea7352230..97b17a97290938f57cee3f230051429945e76e80 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include "config.h"
+#include <sys/time.h>
 #include <cairo-quartz.h>
 #include "gdkprivate-quartz.h"
 
@@ -725,6 +726,39 @@ gdk_quartz_drawable_get_context (GdkDrawable *drawable,
   return GDK_DRAWABLE_IMPL_QUARTZ_GET_CLASS (drawable)->get_context (drawable, antialias);
 }
 
+/* Help preventing "beam synch penalty" where CG makes all graphics code
+ * block until the next vsync if we try to flush (including call display on
+ * a view) too often. We do this by limiting the manual flushing done
+ * outside of expose calls to less than 20Hz, this should leave enough room
+ * for the 60Hz max rate including the "regular" flushing.
+ *
+ * If cg_context is NULL, no flushing is done, only registering that a flush
+ * was made externally.
+ */
+void
+_gdk_quartz_drawable_flush (CGContextRef cg_context)
+{
+  static struct timeval prev_tv;
+  struct timeval tv;
+  gint ms;
+
+  gettimeofday (&tv, NULL);
+
+  if (cg_context)
+    {
+      ms = (tv.tv_sec - prev_tv.tv_sec) * 1000 + (tv.tv_usec - prev_tv.tv_usec) / 1000;
+
+      /* ~20Hz. */
+      if (ms > 50)
+        {
+          CGContextFlush (cg_context);
+          prev_tv = tv;
+        }
+    }
+  else
+    prev_tv = tv;
+}
+
 void
 gdk_quartz_drawable_release_context (GdkDrawable  *drawable, 
                                     CGContextRef  cg_context)
@@ -738,7 +772,10 @@ gdk_quartz_drawable_release_context (GdkDrawable  *drawable,
 
       /* See comment in gdk_quartz_drawable_get_context(). */
       if (window_impl->in_paint_rect_count == 0)
-        [window_impl->view unlockFocus];
+        {
+          _gdk_quartz_drawable_flush (cg_context);
+          [window_impl->view unlockFocus];
+        }
     }
   else if (GDK_IS_PIXMAP_IMPL_QUARTZ (drawable))
     CGContextRelease (cg_context);
index 299616ff1a14f9e4f839b5319f25bf754d0cd3a2..8bb7ea596ae50359ca2eca75396ad0ff50155fc5 100644 (file)
@@ -180,6 +180,7 @@ gboolean     _gdk_quartz_keys_is_modifier (guint      keycode);
 
 /* Drawable */
 void        _gdk_quartz_drawable_finish (GdkDrawable *drawable);
+void        _gdk_quartz_drawable_flush  (CGContextRef cg_context);
 
 /* Geometry */
 void        _gdk_quartz_window_scroll      (GdkWindow       *window,
index 0586460a1f22d36692e47ea4443996714585dd5f..f112497e4ff9d402fd0581ff65a78f5c1fe9ef8b 100644 (file)
@@ -424,6 +424,8 @@ _gdk_windowing_after_process_all_updates (void)
 
       [[nswindow contentView] displayIfNeeded];
 
+      _gdk_quartz_drawable_flush (NULL);
+
       [nswindow enableFlushWindow];
       [nswindow flushWindow];
       [nswindow release];